package com.nwpu.am.controller.common;

import com.nwpu.am.constant.ErrorConstant;
import com.nwpu.am.constant.JwtClaimsConstant;
import com.nwpu.am.constant.RoleConstant;
import com.nwpu.am.constant.properties.JwtProperties;
import com.nwpu.am.constant.properties.MD5Properties;
import com.nwpu.am.constant.properties.RedisProperties;
import com.nwpu.am.pojo.dto.UserLoginDTO;
import com.nwpu.am.pojo.dto.UserPasswordDTO;
import com.nwpu.am.pojo.entity.User;
import com.nwpu.am.pojo.vo.UserLoginVO;
import com.nwpu.am.result.Result;
import com.nwpu.am.service.UserService;
import com.nwpu.am.utils.JwtUtil;
import com.nwpu.am.utils.MD5Util;
import com.nwpu.am.utils.ThreadLocalUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * CommonController
 *
 * @author Roy
 * @version 1.0
 * {@code @date} 2024/6/3
 */

@RestController
@RequestMapping("/common")
@Slf4j
@Api(tags = "员工通用接口")
public class CommonController {
    @Resource
    private UserService userService;
    @Resource
    private JwtProperties jwtProperties;
    @Resource
    private MD5Properties md5Properties;
    @Resource
    private RedisProperties redisProperties;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostMapping("/login")
    @ApiOperation("登录接口")
    public Result<UserLoginVO> login(@RequestBody @Validated UserLoginDTO userLoginDTO) {
        // 验证用户名和密码
        User user = userService.findByUsername(userLoginDTO.getUsername());
        if (user != null) {
            String encryptedPassword = MD5Util.getMD5AsHexWithSalt(
                    userLoginDTO.getPassword(),
                    md5Properties.getSalt(),
                    md5Properties.getIterations()
            );
            if (!encryptedPassword.equals(user.getPassword())) {
                return Result.error(ErrorConstant.WRONG_PASSWORD);
            }
        } else {
            return Result.error(ErrorConstant.USER_NOT_FIND);
        }

        // 储存登录态信息
        ThreadLocalUtil.set(user);
        // 脱敏
        user.setPassword(null);

        // 生成jwt令牌
        HashMap<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_INFO, user);
        String token = JwtUtil.createJWT(
                jwtProperties.getUserSecretKey(),
                jwtProperties.getUserTtl(),
                claims
        );
        // 把token存储在redis中
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        operations.set(token, token, redisProperties.getRedisTtl(), TimeUnit.HOURS);
        log.info("用户登录user：{}", user.getUsername());
        return Result.success(UserLoginVO.userCopy(user, token));
    }

    @PostMapping("/logout")
    @ApiOperation("登出接口")
    public Result<String> logout(@RequestHeader("Authorization") String token) {
        log.info("用户登出user：{}", ThreadLocalUtil.get().toString());
        // 删除登录态
        if (ThreadLocalUtil.get() != null) {
            ThreadLocalUtil.remove();
        }
        // 删除redis信息
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        if (operations.get(token) != null) {
            operations.getOperations().delete(token);
        }
        return Result.success();
    }

    @PutMapping("/update")
    @ApiOperation("更新用户信息")
    public Result<String> update(@RequestBody @Validated User user) {
        // 普通用户只能修改个人信息
        User currentUser = ThreadLocalUtil.get();
        if (currentUser.getRole() == RoleConstant.STAFF_CODE) {
            if (!Objects.equals(currentUser.getUserId(), user.getUserId())) {
                return Result.error(ErrorConstant.UPDATE_WRONG);
            }
        } else {
            log.info("用户信息更新：{}", user);
            return userService.update(user) == 1 ?
                    Result.success() :
                    Result.error(ErrorConstant.UPDATE_WRONG);
        }
        return Result.success();
    }

    @PatchMapping("/updatePassword")
    @ApiOperation("更新当前用户密码")
    public Result<String> updatePassword(@RequestBody @Validated UserPasswordDTO userPasswordDTO) {
        log.info("更新用户密码userId：{}", userPasswordDTO.getUserId());
        Long userId = userPasswordDTO.getUserId();
        String oldPassword = userPasswordDTO.getOldPassword();
        String newPassword = userPasswordDTO.getNewPassword();
        String rePassword = userPasswordDTO.getRePassword();
        // 获取当前用户
        User currentUser = ThreadLocalUtil.get();
        // id是否正确
        if (!Objects.equals(currentUser.getUserId(), userId)) {
            return Result.error(ErrorConstant.WRONG_ID);
        }
        // 判断旧密码是否正确
        User currentUserWithPassword = userService.findByUsername(currentUser.getUsername());
        String encryptedPassword = MD5Util.getMD5AsHexWithSalt(oldPassword, md5Properties.getSalt(), md5Properties.getIterations());
        if (!encryptedPassword.equals(currentUserWithPassword.getPassword())) {
            return Result.error(ErrorConstant.WRONG_PASSWORD);
        }
        // 判断两次新密码是否相同
        if (!newPassword.equals(rePassword)) {
            return Result.error(ErrorConstant.DIFFERENT_PASSWORD);
        }
        return userService.updatePassword(userId, newPassword) == 1 ?
                Result.success() :
                Result.error(ErrorConstant.UPDATE_WRONG);
    }
}
